package com.md.api.common.utils;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.alibaba.fastjson.JSONObject;
import com.aliyun.facebody20191230.models.*;
import com.aliyun.ocr20191230.models.RecognizeQrCodeResponse;
import com.aliyun.tea.TeaException;
import com.aliyun.tea.TeaModel;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.exceptions.ServerException;
import com.google.gson.Gson;
import com.md.api.entity.util.GetFaceResult;
import com.md.api.entity.util.SearchFaceResult;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.springframework.web.multipart.MultipartFile;
import sun.misc.BASE64Decoder;

import java.io.IOException;
import java.net.URI;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author lihao
 * @create 2023-04-13 13:44
 * @desc
 **/
@Slf4j
public class FaceRecognitionUtil {
    /**
     * 阿里云控制台获取 access key
     */
    private static final String ACCESSKEY="LTAI5tHDKkWuYAwBpn7D5VAa";

    /**
     * 阿里云控制台获取 access secret
     */
    private static final String SECRET="GvW7356tmMS5yPY5lVJalyMHLHt7YH";

    private static com.aliyun.facebody20191230.Client client;

    private static com.aliyun.ocr20191230.Client ocrClient;

    private static final String API_HTTP_METHOD = "POST";
    // API访问域名，与类目相关，具体类目的API访问域名请参考：https://help.aliyun.com/document_detail/143103.html
    private static final String API_ENDPOINT = "facebody.cn-shanghai.aliyuncs.com";
    // API版本，与类目相关，具体类目的API版本请参考：https://help.aliyun.com/document_detail/464194.html
    private static final String API_VERSION = "2019-12-30";
    private static final java.text.SimpleDateFormat DF = new java.text.SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");

    public static List<String> faceDbIds = new ArrayList<>();
    static {
        faceDbIds.add("1b92be18cffc48ba8bf801e6a6e355c3");
        faceDbIds.add("21a82804134f40338be0375cfed9335e");
        faceDbIds.add("28982a3638ac43cfb915b325f097ee8a");
        faceDbIds.add("417bf477fdcf482293e32899fed53c5c");
        faceDbIds.add("429fb3de165c4b8da351bdb17a976ef7");
        faceDbIds.add("8e453b7f0b334e28bb4c0d7891c567fe");
        faceDbIds.add("971ce364932d45d5b3bcbd7a394796aa");
        faceDbIds.add("97f0ae0124864202b052b146f692c020");
        faceDbIds.add("a0178316b4a64b8d8369b1e14a5fc161");
        faceDbIds.add("c5ecfe1c11744e0d90c0e6034460fe60");
    }

    /**
     * 使用AK&SK初始化账号Client
     * @return Client
     * @throws Exception
     */
    private static void createClient(){
        com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config()
                // 您的 AccessKey ID
                .setAccessKeyId(ACCESSKEY)
                // 您的 AccessKey Secret
                .setAccessKeySecret(SECRET);
        // 2、访问的域名。注意：这个地方需要求改为相应类目的域名，参考：https://help.aliyun.com/document_detail/143103.html
        config.endpoint = "facebody.cn-shanghai.aliyuncs.com";
        // 3、这里只是以ocr为例，其他能力请使用相应类目的包下面的Client类
        try {
            client=new com.aliyun.facebody20191230.Client(config);
        } catch (Exception e) {
            e.printStackTrace();
            log.info("初始化人脸识别client失败!");
        }
    }

    /**
     * 使用AK&SK初始化账号ocrClient
     * @return Client
     * @throws Exception
     */
    private static void createOcrClient(){
        com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config()
                // 您的 AccessKey ID
                .setAccessKeyId(ACCESSKEY)
                // 您的 AccessKey Secret
                .setAccessKeySecret(SECRET);
        // 2、访问的域名。注意：这个地方需要求改为相应类目的域名，参考：https://help.aliyun.com/document_detail/143103.html
        config.endpoint = "ocr.cn-shanghai.aliyuncs.com";
        // 3、这里只是以ocr为例，其他能力请使用相应类目的包下面的Client类
        try {
            ocrClient=new com.aliyun.ocr20191230.Client(config);
        } catch (Exception e) {
            e.printStackTrace();
            log.info("初始化图像识别client失败!");
        }
    }

    /**
     * 创建人脸数据库
     * @param dbName 数据库名称
     */
    public static void createFaceDb(String dbName) {
        createClient();
        com.aliyun.facebody20191230.models.CreateFaceDbRequest createFaceDbRequest = new com.aliyun.facebody20191230.models.CreateFaceDbRequest()
                .setName(dbName);
        com.aliyun.teautil.models.RuntimeOptions runtime = new com.aliyun.teautil.models.RuntimeOptions();
        try {
            // 复制代码运行请自行打印 API 的返回值
            CreateFaceDbResponse createFaceDbResponse = client.createFaceDbWithOptions(createFaceDbRequest, runtime);
            // 获取整体结果
            log.info(com.aliyun.teautil.Common.toJSONString(TeaModel.buildMap(createFaceDbResponse)));
        } catch (TeaException teaException) {
            teaException.printStackTrace();
            // 获取整体报错信息
            System.out.println(com.aliyun.teautil.Common.toJSONString(teaException));
            // 获取单个字段
            System.out.println(teaException.getCode());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    /**
     * 添加人脸样本
     * @param dbName 数据库名称
     * @param entityId 实体ID
     * @param imageUrl 地址
     */
    public static String addFaceData(String dbName, String entityId,String imageUrl){
        createClient();
        try {
            com.aliyun.facebody20191230.models.AddFaceRequest addFaceRequest = new com.aliyun.facebody20191230.models.AddFaceRequest()
                    .setDbName(dbName)
                    .setEntityId(entityId)
                    .setImageUrl(URLDecoder.decode(imageUrl,"UTF-8"));
            //.setExtraData();自定义信息
            com.aliyun.teautil.models.RuntimeOptions runtime = new com.aliyun.teautil.models.RuntimeOptions();

            AddFaceResponse addFaceResponse = client.addFaceWithOptions(addFaceRequest, runtime);
            String faceId = addFaceResponse.getBody().getData().faceId;
            // 获取整体结果
            log.info("添加人脸数据返回faceId:{},结果===>{}",faceId,com.aliyun.teautil.Common.toJSONString(TeaModel.buildMap(addFaceResponse)));
            return faceId;
        } catch (TeaException teaException) {
            teaException.printStackTrace();
            // 获取整体报错信息
            System.out.println(com.aliyun.teautil.Common.toJSONString(teaException));
            // 获取单个字段
            System.out.println(teaException.getCode());
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }


    /**
     * 添加人脸样本
     * @param dbName 数据库名称
     * @param entityId 实体ID
     * @param labels 标签
     */
    public static void addFaceEntity(String dbName, String entityId,String labels){
        createClient();
        com.aliyun.facebody20191230.models.AddFaceEntityRequest addFaceEntityRequest = new com.aliyun.facebody20191230.models.AddFaceEntityRequest()
                .setDbName(dbName)
                .setEntityId(entityId)
                .setLabels(labels);
        com.aliyun.teautil.models.RuntimeOptions runtime = new com.aliyun.teautil.models.RuntimeOptions();
        try {
            AddFaceEntityResponse addFaceEntityResponse = client.addFaceEntityWithOptions(addFaceEntityRequest, runtime);
            // 获取整体结果
            log.info("添加人脸样本返回结果===>{}",com.aliyun.teautil.Common.toJSONString(TeaModel.buildMap(addFaceEntityResponse)));
        } catch (TeaException teaException) {
            teaException.printStackTrace();
            // 获取整体报错信息
            System.out.println(com.aliyun.teautil.Common.toJSONString(teaException));
            // 获取单个字段
            System.out.println(teaException.getCode());
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    /**
     * 查询人脸样本
     * @param dbName 数据库名称
     * @param entityId 实体ID
     */
    public static GetFaceResult getFaceEntity(String dbName, String entityId)
    {
        createClient();
        com.aliyun.facebody20191230.models.GetFaceEntityRequest getFaceEntityRequest = new com.aliyun.facebody20191230.models.GetFaceEntityRequest()
                .setDbName(dbName)
                .setEntityId(entityId);
        com.aliyun.teautil.models.RuntimeOptions runtime = new com.aliyun.teautil.models.RuntimeOptions();
        try{
            GetFaceEntityResponse getFaceEntityResponse = client.getFaceEntityWithOptions(getFaceEntityRequest, runtime);
            log.info("查询人脸样本：");
            log.info(new Gson().toJson(getFaceEntityResponse));
            return BeanUtil.copyProperties(getFaceEntityResponse.getBody().getData(),GetFaceResult.class);
        } catch (ServerException e) {
            e.printStackTrace();
            log.info("ErrCode:" + e.getErrCode());
            log.info("ErrMsg:" + e.getErrMsg());
            log.info("RequestId:" + e.getRequestId());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 查询人脸样本列表
     * @param dbName 数据库名称
     * @param Offset 起始记录
     */
    public static void listFaceEntities(String dbName, Integer Offset) throws Exception {
        createClient();
        com.aliyun.facebody20191230.models.ListFaceEntitiesRequest listFaceEntitiesRequest = new com.aliyun.facebody20191230.models.ListFaceEntitiesRequest()
                .setDbName(dbName)
                .setOffset(Offset);
        com.aliyun.teautil.models.RuntimeOptions runtime = new com.aliyun.teautil.models.RuntimeOptions();
        try{
            ListFaceEntitiesResponse listFaceEntitiesResponse = client.listFaceEntitiesWithOptions(listFaceEntitiesRequest, runtime);
            log.info("查询人脸样本列表：");
            log.info(new Gson().toJson(listFaceEntitiesResponse));
        } catch (ServerException e) {
            log.info("ErrCode:" + e.getErrCode());
            log.info("ErrMsg:" + e.getErrMsg());
            log.info("RequestId:" + e.getRequestId());
        }
    }

    /**
     * 更新人脸样本
     * @param dbName 数据库名称
     * @param entityId 实体ID
     * @param labels 标签名称
     */
    public static void updateFaceEntity(String dbName, String entityId, String labels){
        createClient();
        com.aliyun.facebody20191230.models.UpdateFaceEntityRequest updateFaceEntityRequest = new com.aliyun.facebody20191230.models.UpdateFaceEntityRequest()
                .setDbName(dbName)
                .setEntityId(entityId)
                .setLabels(labels);
        com.aliyun.teautil.models.RuntimeOptions runtime = new com.aliyun.teautil.models.RuntimeOptions();
        try{
            UpdateFaceEntityResponse updateFaceEntityResponse = client.updateFaceEntityWithOptions(updateFaceEntityRequest, runtime);
            log.info("更新人脸样本：");
            log.info(new Gson().toJson(updateFaceEntityResponse));
        } catch (ServerException e) {
            e.printStackTrace();
            log.info("ErrCode:" + e.getErrCode());
            log.info("ErrMsg:" + e.getErrMsg());
            log.info("RequestId:" + e.getRequestId());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 删除人脸样本
     * @param dbName 数据库名称
     * @param entityId 实体ID
     */
    public static void deleteFaceEntity(String dbName, String entityId)
    {
        createClient();
        com.aliyun.facebody20191230.models.DeleteFaceEntityRequest deleteFaceEntityRequest = new com.aliyun.facebody20191230.models.DeleteFaceEntityRequest()
                .setDbName(dbName)
                .setEntityId(entityId);
        com.aliyun.teautil.models.RuntimeOptions runtime = new com.aliyun.teautil.models.RuntimeOptions();
        try{
            DeleteFaceEntityResponse deleteFaceEntityResponse = client.deleteFaceEntityWithOptions(deleteFaceEntityRequest, runtime);
            log.info("删除人脸样本：");
            log.info(new Gson().toJson(deleteFaceEntityResponse));
        } catch (ServerException e) {
            e.printStackTrace();
        } catch (ClientException e) {
            log.info("ErrCode:" + e.getErrCode());
            log.info("ErrMsg:" + e.getErrMsg());
            log.info("RequestId:" + e.getRequestId());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 查看数据库列表
     */
    public static void listFaceDbs()
    {
        createClient();
        com.aliyun.facebody20191230.models.ListFaceDbsRequest listFaceDbsRequest = new com.aliyun.facebody20191230.models.
                ListFaceDbsRequest();
        com.aliyun.teautil.models.RuntimeOptions runtime = new com.aliyun.teautil.models.RuntimeOptions();
        try {
            ListFaceDbsResponse response = client.listFaceDbsWithOptions(listFaceDbsRequest, runtime);
            log.info("查看数据库列表: ");
            log.info(new Gson().toJson(response));
        } catch (ServerException e) {
            e.printStackTrace();
        } catch (ClientException e) {
            log.info("ErrCode:" + e.getErrCode());
            log.info("ErrMsg:" + e.getErrMsg());
            log.info("RequestId:" + e.getRequestId());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 添加人脸数据  file 格式
     * @param dbName 数据库名称
     * @param entityId 实体ID
     * @param file 人脸图片
     */
    public static void addFace(String dbName, String entityId, MultipartFile file) {
        createClient();
        try{
            com.aliyun.facebody20191230.models.AddFaceAdvanceRequest addFaceRequest = new com.aliyun.facebody20191230.models.AddFaceAdvanceRequest()
                    .setDbName(dbName)
                    .setEntityId(entityId)
                    .setImageUrlObject(file.getInputStream());
            com.aliyun.teautil.models.RuntimeOptions runtime = new com.aliyun.teautil.models.RuntimeOptions();
            AddFaceResponse addFaceResponse = client.addFaceAdvance(addFaceRequest, runtime);
            log.info("添加人脸数据：");
            log.info(new Gson().toJson(addFaceResponse));
        } catch (ServerException e) {
            e.printStackTrace();
        } catch (ClientException e) {
            log.info("ErrCode:" + e.getErrCode());
            log.info("ErrMsg:" + e.getErrMsg());
            log.info("RequestId:" + e.getRequestId());
        }
        catch (IOException e) {
            e.printStackTrace();
        }catch (Exception e) {
            e.printStackTrace();
        }
    }

//    /**
//     * base64转MultipartFile
//     * @param base64
//     * @return
//     */
//    public static MultipartFile base64ToMultipart(String base64) {
//        try {
//            String[] baseStrs = base64.split(",");
//            BASE64Decoder decoder = new BASE64Decoder();
//            byte[] b;
//            b = decoder.decodeBuffer(baseStrs[1]);
//            for(int i = 0; i < b.length; ++i) {
//                if (b[i] < 0) {
//                    b[i] += 256;
//                }
//            }
//            return new BASE64DecodedMultipartFile(b, baseStrs[0]);
//        } catch (IOException e) {
//            e.printStackTrace();
//            return null;
//        }
//    }



    /**
     * 搜索人脸
     * @param dbName 数据库名称
     * @param file 图片
     */
    public static List<SearchFaceResult> searchFace(String dbName, MultipartFile file)
    {
        createClient();
        try{
            com.aliyun.facebody20191230.models.SearchFaceAdvanceRequest searchFaceRequest = new com.aliyun.facebody20191230.models.SearchFaceAdvanceRequest()
                    .setDbName(dbName).setImageUrlObject(file.getInputStream()).setLimit(100);
            com.aliyun.teautil.models.RuntimeOptions runtime = new com.aliyun.teautil.models.RuntimeOptions();
            SearchFaceResponse searchFaceResponse = client.searchFaceAdvance(searchFaceRequest, runtime);
            if(searchFaceResponse.statusCode ==200){
                //请求成功以后映射返回值
                List<SearchFaceResponseBody.SearchFaceResponseBodyDataMatchList> list =searchFaceResponse.getBody().getData().getMatchList();
                List<SearchFaceResult> listResult = new ArrayList<>();
                for (SearchFaceResponseBody.SearchFaceResponseBodyDataMatchList dataMatchList :list){
                    for (SearchFaceResponseBody.SearchFaceResponseBodyDataMatchListFaceItems faceItem:dataMatchList.getFaceItems()){
                        SearchFaceResult  searchFaceResult = BeanUtil.copyProperties(faceItem,SearchFaceResult.class);
                        log.info("人脸识别返回人脸数据："+searchFaceResult);
                        //判断相识度千分之一   三个参考阈值为0.35，0.45和0.6，分别对应千分之一，万分之一和十万分之一的误识率
                        if(searchFaceResult.getScore() >0.35){
                            listResult.add(searchFaceResult);
                        }
                    }
                }
                return listResult;
            }
        } catch (ServerException e) {
            e.printStackTrace();
        } catch (ClientException e) {
            log.info("ErrCode:" + e.getErrCode());
            log.info("ErrMsg:" + e.getErrMsg());
            log.info("RequestId:" + e.getRequestId());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 删除人脸
     * @param dbName 数据库名称
     * @param faceId 人脸数据ID
     */
    public static void deleteFace(String dbName, String faceId)
    {
        createClient();
        com.aliyun.facebody20191230.models.DeleteFaceRequest deleteFaceRequest = new com.aliyun.facebody20191230.models.DeleteFaceRequest()
                .setDbName(dbName).setFaceId(faceId);
        com.aliyun.teautil.models.RuntimeOptions runtime = new com.aliyun.teautil.models.RuntimeOptions();
        try{
            DeleteFaceResponse deleteFaceResponse = client.deleteFaceWithOptions(deleteFaceRequest, runtime);
            log.info("删除人脸：");
            log.info(new Gson().toJson(deleteFaceResponse));
        } catch (ServerException e) {
            e.printStackTrace();
        } catch (ClientException e) {
            log.info("ErrCode:" + e.getErrCode());
            log.info("ErrMsg:" + e.getErrMsg());
            log.info("RequestId:" + e.getRequestId());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 删除人脸数据库
     * @param dbName 数据库名称
     */
    public static void deleteFaceDb(String dbName)
    {
        createClient();
        com.aliyun.facebody20191230.models.DeleteFaceDbRequest deleteFaceDbRequest = new com.aliyun.facebody20191230.models.DeleteFaceDbRequest()
                .setName(dbName);
        com.aliyun.teautil.models.RuntimeOptions runtime = new com.aliyun.teautil.models.RuntimeOptions();
        try{
            DeleteFaceDbResponse deleteFaceDbResponse = client.deleteFaceDbWithOptions(deleteFaceDbRequest, runtime);
            log.info("删除数据库：");
            log.info(new Gson().toJson(deleteFaceDbResponse));
        } catch (ServerException e) {
            e.printStackTrace();
        } catch (ClientException e) {
            log.info("ErrCode:" + e.getErrCode());
            log.info("ErrMsg:" + e.getErrMsg());
            log.info("RequestId:" + e.getRequestId());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 人脸对比
     * @param imageURLA 待对比图片URL地址A
     * @param imageURLB 待对比图片URL地址B
     */
    public static void compareFace(String imageURLA, String imageURLB)
    {
        createClient();
        com.aliyun.facebody20191230.models.CompareFaceRequest compareFaceRequest = new com.aliyun.facebody20191230.models.CompareFaceRequest()
                .setImageDataA(imageURLA)
                .setImageDataB(imageURLB);
        com.aliyun.teautil.models.RuntimeOptions runtime = new com.aliyun.teautil.models.RuntimeOptions();
        try{
            CompareFaceResponse compareFaceResponse = client.compareFaceWithOptions(compareFaceRequest, runtime);
            log.info("人脸对比：");
            log.info(new Gson().toJson(compareFaceResponse));
        } catch (ServerException e) {
            e.printStackTrace();
        } catch (ClientException e) {
            log.info("ErrCode:" + e.getErrCode());
            log.info("ErrMsg:" + e.getErrMsg());
            log.info("RequestId:" + e.getRequestId());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 人脸对比  通过文件比对
     * @param fileA 待对比图片A
     * @param fileB 待对比图片B
     */
    public static void compareFace(MultipartFile fileA, MultipartFile fileB)
    {
        createClient();
        try{
            com.aliyun.facebody20191230.models.CompareFaceAdvanceRequest compareFaceRequest = new com.aliyun.facebody20191230.models.CompareFaceAdvanceRequest()
                    .setImageURLAObject(fileA.getInputStream())
                    .setImageURLBObject(fileB.getInputStream());
            com.aliyun.teautil.models.RuntimeOptions runtime = new com.aliyun.teautil.models.RuntimeOptions();
            CompareFaceResponse compareFaceResponse = client.compareFaceAdvance(compareFaceRequest, runtime);
            log.info("人脸对比：");
            log.info(new Gson().toJson(compareFaceResponse));
        } catch (ServerException e) {
            e.printStackTrace();
        } catch (ClientException e) {
            log.info("ErrCode:" + e.getErrCode());
            log.info("ErrMsg:" + e.getErrMsg());
            log.info("RequestId:" + e.getRequestId());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 人脸检测
     * @param fullPath
     */
    public static Boolean detectFace(String fullPath){
        createClient();
        com.aliyun.facebody20191230.models.DetectFaceRequest detectFaceRequest = new com.aliyun.facebody20191230.models.DetectFaceRequest()
                .setImageURL(fullPath);
        com.aliyun.teautil.models.RuntimeOptions runtime = new com.aliyun.teautil.models.RuntimeOptions();
        detectFaceRequest.setLandmark(false);
        detectFaceRequest.setQuality(false);
        detectFaceRequest.setPose(false);
        detectFaceRequest.setMaxFaceNumber(1l);
        try {
            DetectFaceResponse detectFaceResponse = client.detectFaceWithOptions(detectFaceRequest, runtime);
            if (detectFaceResponse.getStatusCode()==200){
                // 获取整体结果
                System.out.println("人脸检测:"+com.aliyun.teautil.Common.toJSONString(TeaModel.buildMap(detectFaceResponse)));
                return true;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }


    /**
     * 人脸活体检测
     * @param file
     */
    public static Boolean detectLivingFace(MultipartFile file){
        createClient();
        try{
            com.aliyun.facebody20191230.models.DetectLivingFaceAdvanceRequest.DetectLivingFaceAdvanceRequestTasks tasks0 = new com.aliyun.facebody20191230.models.DetectLivingFaceAdvanceRequest.DetectLivingFaceAdvanceRequestTasks()
                    .setImageURLObject(file.getInputStream());
            com.aliyun.facebody20191230.models.DetectLivingFaceAdvanceRequest detectLivingFaceRequest = new com.aliyun.facebody20191230.models.DetectLivingFaceAdvanceRequest()
                    .setTasks(java.util.Arrays.asList(
                            tasks0
                    ));
            com.aliyun.teautil.models.RuntimeOptions runtime = new com.aliyun.teautil.models.RuntimeOptions();
            DetectLivingFaceResponse response = client.detectLivingFaceAdvance(detectLivingFaceRequest, runtime);
            if(response.getStatusCode()==200){
                if("normal".equals(response.getBody().getData().getElements().get(0).getResults().get(0).getLabel())){
                    return true;
                }
            }
            log.info("人脸活体检测:");
            log.info(new Gson().toJson(response));
        } catch (ServerException e) {
            e.printStackTrace();
        } catch (ClientException e) {
            log.info("ErrCode:" + e.getErrCode());
            log.info("ErrMsg:" + e.getErrMsg());
            log.info("RequestId:" + e.getRequestId());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * 人体计数
     * @param file
     * @return 人体的个数
     */
    public static Integer detectBodyCount(MultipartFile file){
        createClient();
        try{
            com.aliyun.facebody20191230.models.DetectBodyCountAdvanceRequest detectBodyCountAdvanceRequest = new com.aliyun.facebody20191230.models.DetectBodyCountAdvanceRequest()
                    .setImageURLObject(file.getInputStream());
            com.aliyun.teautil.models.RuntimeOptions runtime = new com.aliyun.teautil.models.RuntimeOptions();
            DetectBodyCountResponse detectBodyCountResponse = client.detectBodyCountAdvance(detectBodyCountAdvanceRequest, runtime);
            if(detectBodyCountResponse.getStatusCode()==200){
                return detectBodyCountResponse.getBody().getData().getPersonNumber();
            }
            log.info("人体计数:");
            log.info(new Gson().toJson(detectBodyCountResponse));
        } catch (ServerException e) {
            e.printStackTrace();
        } catch (ClientException e) {
            log.info("ErrCode:" + e.getErrCode());
            log.info("ErrMsg:" + e.getErrMsg());
            log.info("RequestId:" + e.getRequestId());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return 0;
    }


    /**
     * 人脸检测与五官定位
     * @param file
     * @return 检测出的人脸个数
     */
    public static Integer detectFace(MultipartFile file){
        createClient();
        try{
            com.aliyun.facebody20191230.models.DetectFaceAdvanceRequest detectFaceRequest = new com.aliyun.facebody20191230.models.DetectFaceAdvanceRequest()
                    .setImageURLObject(file.getInputStream());
            com.aliyun.teautil.models.RuntimeOptions runtime = new com.aliyun.teautil.models.RuntimeOptions();
            DetectFaceResponse detectFaceResponse = client.detectFaceAdvance(detectFaceRequest, runtime);
            if(detectFaceResponse.getStatusCode()==200){
                return detectFaceResponse.getBody().getData().getFaceCount();
            }
            log.info("人脸检测与五官定位:");
            log.info(new Gson().toJson(detectFaceResponse));
        } catch (ServerException e) {
            e.printStackTrace();
        } catch (ClientException e) {
            log.info("ErrCode:" + e.getErrCode());
            log.info("ErrMsg:" + e.getErrMsg());
            log.info("RequestId:" + e.getRequestId());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return 0;
    }

    /**
     * 扫描二维码
     * @param file
     * @return 扫描二维码
     */
    public static void recognizeQrCode(MultipartFile file){
        createOcrClient();
        try{
            com.aliyun.ocr20191230.models.RecognizeQrCodeAdvanceRequest.RecognizeQrCodeAdvanceRequestTasks tasks0 = new com.aliyun.ocr20191230.models.RecognizeQrCodeAdvanceRequest.RecognizeQrCodeAdvanceRequestTasks()
                    .setImageURLObject(file.getInputStream());
            com.aliyun.ocr20191230.models.RecognizeQrCodeAdvanceRequest recognizeQrCodeAdvanceRequest = new com.aliyun.ocr20191230.models.RecognizeQrCodeAdvanceRequest()
                    .setTasks(java.util.Arrays.asList(tasks0));
            com.aliyun.teautil.models.RuntimeOptions runtime = new com.aliyun.teautil.models.RuntimeOptions();
            RecognizeQrCodeResponse response = ocrClient.recognizeQrCodeAdvance(recognizeQrCodeAdvanceRequest, runtime);
            System.out.println(com.aliyun.teautil.Common.toJSONString(TeaModel.buildMap(response)));
            log.info("扫描二维码:");
            log.info(new Gson().toJson(response));
        } catch (ServerException e) {
            e.printStackTrace();
        } catch (ClientException e) {
            log.info("ErrCode:" + e.getErrCode());
            log.info("ErrMsg:" + e.getErrMsg());
            log.info("RequestId:" + e.getRequestId());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }



    public static String getSign(Map<String, String> params) throws Exception {
        // 创建AccessKey ID和AccessKey Secret，请参见：https://help.aliyun.com/document_detail/175144.html
        // 如果您使用的是RAM用户的AccessKey，还需要为子账号授予权限AliyunVIAPIFullAccess，请参见：https://help.aliyun.com/document_detail/145025.html
        // 从环境变量读取配置的AccessKey ID和AccessKey Secret。运行代码示例前必须先配置环境变量。
        DF.setTimeZone(new java.util.SimpleTimeZone(0, "GMT"));// 这里一定要设置GMT时区
        // 业务参数名字是大驼峰
        // 注意，使用签名机制调用，文件参数目前仅支持上海OSS链接，可参考https://help.aliyun.com/document_detail/175142.html文档将文件放入上海OSS中。如果是其他情况（如本地文件或者其他链接），请先显式地转换成上海OSS链接，可参考https://help.aliyun.com/document_detail/155645.html文档中的方式二，但该方案不支持web前端环境直接调用。
        // 对于数组类字段，需要将参数中的N改为从1开始的连续的具体数字，比如参数Tasks.N.ImageURL，需要输入两张图片，则为
//        params.put("Tasks.1.ImageURL", "http://viapi-test.oss-cn-shanghai.aliyuncs.com/viapi-3.0domepic/facebody/DetectLivingFace/DetectLivingFace11.jpg");
//        params.put("Tasks.2.ImageURL", "http://viapi-test.oss-cn-shanghai.aliyuncs.com/viapi-3.0domepic/facebody/DetectLivingFace/DetectLivingFace13.jpg");
        return execute( ACCESSKEY, SECRET, params);
    }


    public static String execute( String accessKeyId, String accessSecret, Map<String, String> bizParams) throws Exception {
        java.util.Map<String, String> params = new java.util.HashMap<String, String>();
        // 1. 系统参数
        params.put("SignatureMethod", "HMAC-SHA1");
        params.put("SignatureNonce", java.util.UUID.randomUUID().toString());//防止重放攻击
        params.put("AccessKeyId", accessKeyId);
        params.put("SignatureVersion", "1.0");
        params.put("Timestamp", DF.format(new java.util.Date()));
        params.put("Format", "JSON");
        // 2. 业务API参数
        params.put("RegionId", "cn-shanghai");
        params.put("Version", API_VERSION);
        if (bizParams != null && !bizParams.isEmpty()) {
            params.putAll(bizParams);
        }
        // 3. 去除签名关键字Key
        if (params.containsKey("Signature")) {
            params.remove("Signature");
        }
        // 4. 参数KEY排序
        java.util.TreeMap<String, String> sortParams = new java.util.TreeMap<String, String>();
        sortParams.putAll(params);
        // 5. 构造待签名的字符串
        java.util.Iterator<String> it = sortParams.keySet().iterator();
        StringBuilder sortQueryStringTmp = new StringBuilder();
        while (it.hasNext()) {
            String key = it.next();
            sortQueryStringTmp.append("&").append(specialUrlEncode(key)).append("=").append(specialUrlEncode(params.get(key)));
        }
        String sortedQueryString = sortQueryStringTmp.substring(1);// 去除第一个多余的&符号
        StringBuilder stringToSign = new StringBuilder();
        stringToSign.append(API_HTTP_METHOD).append("&");
        stringToSign.append(specialUrlEncode("/")).append("&");
        stringToSign.append(specialUrlEncode(sortedQueryString));
        String sign = sign(accessSecret + "&", stringToSign.toString());
        // 6. 签名最后也要做特殊URL编码
        String signature = specialUrlEncode(sign);
        System.out.println(params.get("SignatureNonce"));
        System.out.println("\r\n=========\r\n");
        System.out.println(params.get("Timestamp"));
        System.out.println("\r\n=========\r\n");
        System.out.println(sortedQueryString);
        System.out.println("\r\n=========\r\n");
        System.out.println(stringToSign.toString());
        System.out.println("\r\n=========\r\n");
        System.out.println(sign);
        System.out.println("\r\n=========\r\n");
        System.out.println(signature);
        System.out.println("\r\n=========\r\n");
        // 最终生成出合法请求的URL
        System.out.println("http://" + API_ENDPOINT + "/?Signature=" + signature + sortQueryStringTmp);

        // 添加直接做post请求的方法
        try {
            // 使用生成的 URL 创建POST请求
            URIBuilder builder = new URIBuilder("http://" + API_ENDPOINT + "/?Signature=" + signature + sortQueryStringTmp);
            URI uri = builder.build();
            HttpPost request = new HttpPost(uri);
            HttpClient httpclient = HttpClients.createDefault();
            HttpResponse response = httpclient.execute(request);
            HttpEntity entity = response.getEntity();
            if (entity != null) {
                System.out.println(EntityUtils.toString(entity));
                return null;
            }else{
                return null;
            }
        } catch (Exception e) {
            System.out.println(e.getMessage());
            return null;
        }
    }
    public static String specialUrlEncode(String value) throws Exception {
        return java.net.URLEncoder.encode(value, "UTF-8").replace("+", "%20").replace("*", "%2A").replace("%7E", "~");
    }
    public static String sign(String accessSecret, String stringToSign) throws Exception {
        javax.crypto.Mac mac = javax.crypto.Mac.getInstance("HmacSHA1");
        mac.init(new javax.crypto.spec.SecretKeySpec(accessSecret.getBytes("UTF-8"), "HmacSHA1"));
        byte[] signData = mac.doFinal(stringToSign.getBytes("UTF-8"));
        return new sun.misc.BASE64Encoder().encode(signData);
    }

}
